package com.tomecode.tools.maven.settings.gui.tray;

import java.io.File;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;

import com.tomecode.tools.maven.settings.SettingsFactory;
import com.tomecode.tools.maven.settings.config.Configuration;
import com.tomecode.tools.maven.settings.config.Maven;
import com.tomecode.tools.maven.settings.gui.EditorWindow;
import com.tomecode.tools.maven.settings.gui.FrmListMavens;
import com.tomecode.tools.maven.settings.gui.frm.FrmAbout;
import com.tomecode.tools.maven.settings.gui.images.ImageFactory;
import com.tomecode.tools.maven.settings.model.Profile;
import com.tomecode.tools.maven.settings.model.Settings;

/**
 * System try icon
 * 
 * @author Tomas Frastia
 * @see http://www.tomecode.com or
 *      http://code.google.com/p/maven-settings-editor/
 * 
 */
public final class SystemTray {

	private final Display display;

	private final Tray tray;
	private final TrayItem trayItem;

	private final Shell shell;

	private List<Maven> mavens;

	private Settings activeSettings;

	/**
	 * if is true then all edit options is disabled
	 */
	private boolean isEditorOpen = false;
	/**
	 * active maven
	 */
	private Maven activeMaven;

	public SystemTray() {
		this.display = Display.getDefault();
		this.shell = new Shell(this.display);
		this.shell.setText("Maven Settings Editor");
		shell.setImage(ImageFactory.MAVEN_SETTINGS_EDITOR);
		this.tray = display.getSystemTray();
		this.trayItem = new TrayItem(tray, 0);

		Image img = new Image(display, ImageFactory.class.getResourceAsStream("mavenSettingsEditor16.png"));
		this.trayItem.setToolTipText("Maven Settings Editor");
		this.trayItem.setImage(img);

		this.mavens = Configuration.loadMavens();

		setActiveMaven();
		this.trayItem.addListener(SWT.MenuDetect, new Listener() {
			public final void handleEvent(org.eclipse.swt.widgets.Event event) {
				if (activeMaven == null || activeSettings == null) {
					createStartMenu();
				} else {
					createMenu();
				}
			};
		});

	}

	/**
	 * create a menu that will contain the basic items
	 * 
	 * @param rootMenu
	 */
	private final void createMenuSettingsBasic(Menu rootMenu) {
		MenuItem offline = new MenuItem(rootMenu, SWT.NONE | SWT.CHECK);
		offline.setSelection(activeSettings.isOffline());
		offline.setEnabled(!isEditorOpen);
		offline.addListener(SWT.Selection, new Listener() {

			@Override
			public final void handleEvent(Event event) {
				activeSettings.setOffline(!activeSettings.isOffline());
				updateBasicSettings();
			}
		});
		offline.setText("Offline");
		MenuItem interactiveMode = new MenuItem(rootMenu, SWT.NONE | SWT.CHECK);
		interactiveMode.setSelection(activeSettings.isInteractiveMode());
		interactiveMode.setEnabled(!isEditorOpen);
		interactiveMode.addListener(SWT.Selection, new Listener() {

			@Override
			public final void handleEvent(Event event) {
				activeSettings.setInteractiveMode(!activeSettings.isInteractiveMode());
				updateBasicSettings();
			}
		});
		interactiveMode.setText("Interactive Mode");
		MenuItem usePluginRegistry = new MenuItem(rootMenu, SWT.NONE | SWT.CHECK);
		usePluginRegistry.setSelection(activeSettings.isUsePluginRegistry());
		usePluginRegistry.setEnabled(!isEditorOpen);
		usePluginRegistry.addListener(SWT.Selection, new Listener() {

			@Override
			public final void handleEvent(Event event) {
				activeSettings.setUsePluginRegistry(!activeSettings.isUsePluginRegistry());
				updateBasicSettings();
			}
		});
		usePluginRegistry.setText("Use Plugin Registry");
	}

	/**
	 * create root menu
	 */
	private final void createMenu() {
		Menu rootMenu = new Menu(shell, SWT.POP_UP);
		createMenuSettingsBasic(rootMenu);
		new MenuItem(rootMenu, SWT.SEPARATOR);
		MenuItem reload = new MenuItem(rootMenu, SWT.NONE);
		reload.setText("Refresh");
		reload.setEnabled(!isEditorOpen);
		reload.setImage(ImageFactory.RELOAD);
		reload.addListener(SWT.Selection, new Listener() {
			@Override
			public final void handleEvent(Event event) {
				setActiveMaven();
			}
		});
		new MenuItem(rootMenu, SWT.SEPARATOR);
		MenuItem editor = new MenuItem(rootMenu, SWT.NONE);
		editor.setText("Open Editor");
		editor.setImage(ImageFactory.EDITOR);
		editor.setEnabled(activeSettings != null && !isEditorOpen);
		editor.addListener(SWT.Selection, new Listener() {

			@Override
			public final void handleEvent(Event paramEvent) {
				EditorWindow editorWindow = new EditorWindow();
				isEditorOpen = true;
				Settings newActiveSettings = editorWindow.open(activeMaven);
				if (newActiveSettings != null) {
					activeSettings = newActiveSettings;
				}
				isEditorOpen = false;
			}
		});
		new MenuItem(rootMenu, SWT.SEPARATOR);
		settigsMenu(rootMenu);
		new MenuItem(rootMenu, SWT.SEPARATOR);
		createProfiles(rootMenu);
		new MenuItem(rootMenu, SWT.SEPARATOR);
		createBasicMenu(rootMenu);
		rootMenu.setVisible(true);

	}

	/**
	 * menu: settings->List Of Mavens
	 * 
	 * @param rootMenu
	 */
	private final void settigsMenu(Menu rootMenu) {
		MenuItem settingsItem = new MenuItem(rootMenu, SWT.CASCADE);
		settingsItem.setText("Settings");
		Menu submenuSettings = new Menu(shell, SWT.DROP_DOWN);
		settingsItem.setMenu(submenuSettings);
		MenuItem listOfMavensItem = new MenuItem(submenuSettings, SWT.PUSH);
		listOfMavensItem.setText("List Of Mavens");
		listOfMavensItem.setEnabled(!isEditorOpen);
		listOfMavensItem.addListener(SWT.Selection, new Listener() {

			@Override
			public final void handleEvent(Event paramEvent) {
				FrmListMavens frmListMavens = new FrmListMavens(shell, mavens);
				List<Maven> list = frmListMavens.open();
				if (list != null) {
					mavens = list;
					setActiveMaven();
					Configuration.saveMavens(list);
				}

			}

		});
	}

	/**
	 * create a menu that will contain a list of active profiles
	 * 
	 * @param rootMenu
	 */
	private final void createProfiles(Menu rootMenu) {
		MenuItem profiles = new MenuItem(rootMenu, SWT.CASCADE);
		profiles.setText("Active Profiles");
		Menu profileSubMenu = new Menu(shell, SWT.DROP_DOWN);
		profiles.setMenu(profileSubMenu);
		for (Profile profile : activeSettings.getProfiles()) {
			MenuItem item = new MenuItem(profileSubMenu, SWT.NONE | SWT.CHECK);
			item.setData(profile.getId());
			item.setText(profile.getId());
			item.setEnabled(!isEditorOpen);
			item.setSelection(activeSettings.getActiveProfiles().contains(profile.getId()));
			item.addListener(SWT.Selection, new Listener() {
				@Override
				public final void handleEvent(Event event) {
					String id = (String) event.widget.getData();
					if (activeSettings.getActiveProfiles().contains(id)) {
						activeSettings.getActiveProfiles().remove(id);
					} else {
						activeSettings.getActiveProfiles().add(id);
					}

					updateBasicSettings();
				}
			});
		}
	}

	private final void setActiveMaven() {
		for (Maven maven : mavens) {
			if (maven.isActive()) {
				activeMaven = maven;
				setActiveSettings();
				return;
			}
		}
		activeMaven = null;
		activeSettings = null;
	}

	private final void setActiveSettings() {
		try {
			activeSettings = SettingsFactory.loadSettings(activeMaven);
		} catch (Exception e) {
			MessageBox messageBox = new MessageBox(shell, SWT.ICON_ERROR);
			messageBox.setMessage("Failed parse settings.xml in " + activeMaven.getHome().getPath() + File.separator + "conf" + File.separator + "settings.xml");
			messageBox.setText("Failed parse Settings.xml");
			messageBox.open();

			activeSettings = null;

		}
	}

	private final void updateBasicSettings() {
		try {
			SettingsFactory.save(activeSettings, activeMaven);
		} catch (Exception ex) {
			MessageBox messageBox = new MessageBox(shell, SWT.ICON_ERROR);
			messageBox.setMessage("Failed save settings.xml for Maven:" + activeMaven.getHome().getPath() + ". Reason: " + ex.getMessage());
			messageBox.setText("Failed save settings.xml");
			messageBox.open();
		}
	}

	/**
	 * start menu:
	 * 
	 * settings->List Of Mavens
	 * ----------------------------------------------------------------------
	 * about
	 * ----------------------------------------------------------------------
	 * exit
	 */
	private final void createStartMenu() {
		Menu rootMenu = new Menu(shell, SWT.POP_UP);
		settigsMenu(rootMenu);
		new MenuItem(rootMenu, SWT.SEPARATOR);
		createBasicMenu(rootMenu);
		rootMenu.setVisible(true);
	}

	/**
	 * create basic menu
	 * 
	 * @return
	 */
	private final void createBasicMenu(Menu rootMenu) {

		MenuItem about = new MenuItem(rootMenu, SWT.NONE);
		about.setText("About");
		about.addListener(SWT.Selection, new Listener() {
			@Override
			public final void handleEvent(Event paramEvent) {
				FrmAbout frmAbout = new FrmAbout(shell);
				frmAbout.open();
			}
		});
		new MenuItem(rootMenu, SWT.SEPARATOR);
		MenuItem exit = new MenuItem(rootMenu, SWT.NONE);
		exit.addListener(SWT.Selection, new Listener() {

			@Override
			public final void handleEvent(Event paramEvent) {
				display.close();
			}
		});
		exit.setImage(ImageFactory.EXIT);
		exit.setText("Exit");
	}

	public final void open() {
		try {
			while (true) {
				if (!display.readAndDispatch())
					display.sleep();
			}
		} catch (Exception e) {
			display.dispose();
		}

	}
}
